package metu.tespit.session.accountManagement;

import java.io.File;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.SecureRandom;

import javax.persistence.EntityManager;

import metu.tespit.entitiy.accountManagement.User;
import metu.tespit.session.EntityManager.ExtendedEntityHome;
import metu.tespit.session.util.Events;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.async.Asynchronous;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.faces.Renderer;
import org.jboss.seam.util.Base64;
import org.richfaces.event.UploadEvent;
import org.richfaces.model.UploadItem;

/**
 
 * @created 01 Nis 2012
 */
@Name("userHome")
@Scope(ScopeType.CONVERSATION)
public class UserHome extends ExtendedEntityHome<User> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7881998422644087235L;
	@RequestParameter String userName;
	private String password;
	private String firstPass;
	private String secondPass;

	private String passToSend;

	private byte[] image;

	private final String saltstr="C47t1TuP6=4159W";
	
	private User mailToUser;

	public Long getUserId() {
		return (Long) getId();
	}

	public void setUserId(Long userId) {
		setId(userId);
	}

	private String path;

	@In
	EntityManager entityManager;

	// edit from AccountDetails

	public void setInstanceFromUserName(){

		// Dikkat, getSingleResult sadece sonuç kesin olarak donecegi zaman kullanilmalidir, yoksa exception atar!
		this.setInstance((User)entityManager.createQuery("select user from User user where user.username=:un").setParameter("un", userName).getSingleResult());


	}
	public void setInstanceFromUserName(String username){
		// Dikkat, getSingleResult sadece sonuç kesin olarak donecegi zaman kullanilmalidir, yoksa exception atar!
		this.setInstance((User)entityManager.createQuery("select user from User user where user.username=:un").setParameter("un", username).getSingleResult());


	}

	@Override @Begin
	public void create() {
		super.create();
	}


	@In(create=true)
	private Renderer renderer;

	@Override
	public String persist() {


		SecureRandom random = new SecureRandom();
		String pass= new BigInteger(130, random).toString(36);
		pass=pass.substring(0,6);

		System.out.println( pass );
	
		try {
			this.instance.setPassword(getHash(pass,saltstr));
			String s= super.persist();
			passToSend =(pass);

			if (s.equalsIgnoreCase("persisted")){
				raiseTransactionSuccessEvent(Events.USER_CREATED, this.instance, passToSend);
			}
				

			passToSend =(null);
			return s;

		} catch (Exception e) {

			e.printStackTrace();
			return "fault";
		}

	}
	
	@Observer(Events.USER_CREATED)
	@Asynchronous
	public void sendEmail(User user, String passToSend){
		this.mailToUser = user;
		this.passToSend = passToSend;
		
		renderer.render("/Mail/createUser.xhtml");
	}

	
	public void uploadImage(UploadEvent event) throws Exception{
		UploadItem item = event.getUploadItem();
		this.instance.setPicture(item.getData());
		this.update();
	}  
	
	public String update(){

		String s = super.update();

		return s;

	}

	public boolean checkAccessPermission(String username){
		if(this.instance != null){
			return this.instance.getUsername().equals(username);
		}else{
			return username.equals(this.userName);
		}
		
	}
	
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getFirstPass() {
		return firstPass;
	}

	public void setFirstPass(String firstPass) {
		this.firstPass = firstPass;
	}

	public String getSecondPass() {
		return secondPass;
	}

	public void setSecondPass(String secondPass) {
		this.secondPass = secondPass;
	}


	public void listener(UploadEvent event) throws Exception{
		UploadItem item = event.getUploadItem();
		File file =item.getFile();
		RandomAccessFile f = new RandomAccessFile(file, "r");
		
		byte[] b = new byte[(int)f.length()];
		f.read(b);
		image=b;
		
	}  

	//TODO: add screen message and remove sysouts
	public String savePass(){
		try {
			if(this.instance.getPassword().equals(getHash(password,saltstr))){
				if(secondPass.equals(firstPass)){

					this.instance.setPassword(getHash(secondPass,saltstr));
					String s=super.persist();
					System.out.println(s);
					return s;

				}

				else 
				{
					System.out.println("1");
					return "MatchError";
				}
			}
			else {
				System.out.println(2);
				return "PassError";
			}

		} catch (Exception e) {
			e.printStackTrace();
			return "fault";
		}
	}

	private String getHash(String password,String saltPhrase)throws Exception{
		MessageDigest md = MessageDigest.getInstance("MD5");

		md.update(saltPhrase.getBytes());

		byte[] salt = md.digest();

		md.reset();

		md.update(password.getBytes("UTF-8"));

		md.update(salt);

		byte[] raw = md.digest();

		return new String(Base64.encodeBytes(raw));
	}

	public void setPath(String path) {
		this.path=path;
	}

	public String getPath() {
		if(path!=null){
			if(path.equalsIgnoreCase("userList")){
				return "/Settings/User/userList.xhtml";
			}
		}else {
			this.path =  "/home.xhtml";
		}

		return this.path;
	}

	public void setImage(byte[] image) {
		this.image = image;
	}

	public byte[] getImage() {
		return image;
	}

	public void clearImage(){
		setImage(null);
		instance.setPicture(null);
	}

	public String getPassToSend() {
		return passToSend;
	}

	public User getMailToUser() {
		return mailToUser;
	}

	public void setMailToUser(User mailToUser) {
		this.mailToUser = mailToUser;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
	
	
}



